package com.yanfan.iot.service.impl;

import com.yanfan.common.core.domain.AjaxResult;
import com.yanfan.common.core.domain.entity.SysUser;
import com.yanfan.common.utils.DateUtils;
import com.yanfan.iot.domain.AlertLog;
import com.yanfan.iot.domain.vo.AlertLogVo;
import com.yanfan.iot.mapper.AlertLogMapper;
import com.yanfan.iot.model.AlertCountVO;
import com.yanfan.iot.model.DeviceAlertCount;
import com.yanfan.iot.model.param.DataCenterParam;
import com.yanfan.iot.service.IAlertLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static com.yanfan.common.utils.SecurityUtils.getLoginUser;

/**
 * 设备告警Service业务层处理
 *
 * @author kerwincui
 * @date 2022-01-13
 */
@Service
public class AlertLogServiceImpl implements IAlertLogService {
    @Autowired
    private AlertLogMapper alertLogMapper;

    /**
     * 查询设备告警
     *
     * @param alertLogId 设备告警主键
     * @return 设备告警
     */
    @Override
    public AlertLog selectAlertLogByAlertLogId(Long alertLogId) {
        return alertLogMapper.selectAlertLogByAlertLogId(alertLogId);
    }

    /**
     * 查询设备告警列表
     *
     * @param alertLog 设备告警
     * @return 设备告警
     */
    @Override
    public List<AlertLog> selectAlertLogList(AlertLog alertLog) {
        return alertLogMapper.selectAlertLogList(alertLog);
    }

    public List<AlertLog> AlertLogListSceneContext(AlertLog alertLog) {
        return alertLogMapper.selectAlertLogList(alertLog);
    }

    @Override
    public AjaxResult selectAlertLogLists(AlertLog alertLog) {
        AjaxResult ajaxResult = new AjaxResult();
        SysUser user = getLoginUser().getUser();
        // 查询所属机构
        if (null != user.getDeptId()) {
            alertLog.setUserId(user.getDept().getDeptUserId());
        } else {
            alertLog.setUserId(user.getUserId());
        }
        List<AlertLog> alertLogs = alertLogMapper.selectAlertLogList(alertLog);
        //小时数据
        if(alertLog.getDateType().equals("1")){
            // 按照小时分组并统计每个小时的数量
            Map<Integer, Long> hourCountMap = alertLogs.stream()
                    .collect(Collectors.groupingBy(
                            item -> item.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().getHour(),
                            Collectors.counting()
                    ));
            // 填充Map，确保每个小时都有一个初始值0
            for (int i = 0; i < 24; i++) {
                hourCountMap.put(i, 0L);
            }
            // 使用stream来计算每个小时的出现次数
            hourCountMap.replaceAll((key, value) -> value + alertLogs.stream()
                    .filter(item -> ZonedDateTime.ofInstant(item.getCreateTime().toInstant(), ZoneId.systemDefault())
                            .getHour() == key)
                    .count());
            // 创建两个列表，一个用于存储小时，一个用于存储数据
            List<String> hours = new ArrayList<>();
            List<Long> counts = new ArrayList<>();

            IntStream.range(0, 24).forEach(hour -> {
                hours.add(hour+"时");
                counts.add(hourCountMap.getOrDefault(hour, 0L)); // 使用getOrDefault以确保没有数据的小时计数为0
            });
            ajaxResult.put("hours", hours);
            ajaxResult.put("counts", counts);
            return ajaxResult;
        }
        else if(alertLog.getDateType().equals("2")){
            // 按照日分组并统计每天的数量
            Map<LocalDate, Long> dayCountMap = alertLogs.stream()
                    .collect(Collectors.groupingBy(
                            item -> item.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                            Collectors.counting()
                    ));
            // 填充Map，确保每一天都有一个初始值0
            LocalDate startDate = LocalDate.parse(alertLog.getStartDate());
            for (int i = 0; i <= 30; i++) {
                LocalDate date = startDate.plusDays(i);
                dayCountMap.putIfAbsent(date, 0L);
            }
            // 创建两个列表，一个用于存储日期，一个用于存储数据
            List<String> dates = new ArrayList<>();
            List<Long> counts = new ArrayList<>();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d");
            IntStream.range(0, 31).forEach(day -> {
                LocalDate date = startDate.plusDays(day);
                String formattedDate = date.format(formatter); // 使用DateTimeFormatter格式化日期
                dates.add(formattedDate+"日");
                counts.add(dayCountMap.getOrDefault(date, 0L)); // 使用getOrDefault以确保没有数据的日期计数为0
            });
            ajaxResult.put("hours", dates);
            ajaxResult.put("counts", counts);
            return ajaxResult;
        }
        else if(alertLog.getDateType().equals("3")){
            // 按照月分组并统计每个月的数量
            Map<YearMonth, Long> monthCountMap = alertLogs.stream()
                    .collect(Collectors.groupingBy(
                            item -> YearMonth.from(item.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()),
                            Collectors.counting()
                    ));
            // 填充Map，确保每个月都有一个初始值0
            YearMonth thisYear = YearMonth.of(YearMonth.now().getYear(), 1);
            for (int i = 0; i < 12; i++) {
                YearMonth yearMonth = thisYear.plusMonths(i);
                monthCountMap.putIfAbsent(yearMonth, 0L);
            }
            // 创建两个列表，一个用于存储月份，一个用于存储数据
            List<String> months = new ArrayList<>();
            List<Long> counts = new ArrayList<>();

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM"); // 格式化月份，确保两位数
            IntStream.range(0, 12).forEach(month -> {
                YearMonth yearMonth = thisYear.plusMonths(month);
                String formattedDate = yearMonth.format(formatter); // 使用DateTimeFormatter格式化月份
                months.add(formattedDate+"月");
                counts.add(monthCountMap.getOrDefault(yearMonth, 0L)); // 使用getOrDefault以确保没有数据的月份计数为0
            });
            ajaxResult.put("hours", months);
            ajaxResult.put("counts", counts);
            return ajaxResult;
        }
        return ajaxResult;
    }


    @Override
    public List<AlertLog> selectAlertLogListByCreateBy(String createBy, String remark, Integer status) {
        AlertLog alertLog = new AlertLog();
        alertLog.setCreateBy(createBy);
        alertLog.setStatus(status);
        alertLog.setRemark(remark);
        return alertLogMapper.selectAlertLogList(alertLog);
    }

    @Override
    public List<AlertLog> listByztGuid(AlertLog alertLog) {
        return alertLogMapper.listByztGuid(alertLog);
    }

    /**
     * 查询设备告警列表
     *
     * @param alertLog 设备告警
     * @return 设备告警
     */
    @Override
    public Long selectAlertLogListCount(AlertLog alertLog) {
        /*SysUser user = getLoginUser().getUser();
        List<SysRole> roles = user.getRoles();
        for (int i = 0; i < roles.size(); i++) {
            // 租户和用户，只查看自己分组
            if (roles.get(i).getRoleKey().equals("tenant") || roles.get(i).getRoleKey().equals("general")) {
                alertLog.setUserId(user.getUserId());
                break;
            }
        }*/
        return alertLogMapper.selectAlertLogListCount(alertLog);
    }

    @Override
    public List<DeviceAlertCount> selectDeviceAlertCount() {
        return alertLogMapper.selectDeviceAlertCount();
    }

    @Override
    public DeviceAlertCount selectDeviceAlertCountBySN(String serialNumber) {
        return alertLogMapper.selectDeviceAlertCountBySN(serialNumber);
    }

    @Override
    public List<DeviceAlertCount> selectSceneAlertCount() {
        return alertLogMapper.selectSceneAlertCount();
    }

    @Override
    public DeviceAlertCount selectSceneAlertCountBySceneId(String sceneId) {
        return alertLogMapper.selectSceneAlertCountBySceneId(sceneId);
    }

    /**
     * 新增设备告警
     *
     * @param alertLog 设备告警
     * @return 结果
     */
    @Override
    public int insertAlertLog(AlertLog alertLog) {
        alertLog.setCreateTime(DateUtils.getNowDate());
        return alertLogMapper.insertAlertLog(alertLog);
    }

    @Override
    public int insertAlertLogBatch(List<AlertLog> alertLogList) {
        return alertLogMapper.insertAlertLogBatch(alertLogList);
    }

    /**
     * 修改设备告警
     *
     * @param alertLog 设备告警
     * @return 结果
     */
    @Override
    public int updateAlertLog(AlertLog alertLog) {
        alertLog.setUpdateTime(DateUtils.getNowDate());
        if (alertLog.getRemark().length() > 0) {
            // 1=不需要处理,2=未处理,3=已处理
            alertLog.setStatus(3);
        }
        return alertLogMapper.updateAlertLog(alertLog);
    }

    @Override
    public int updateAlertLogStatus(AlertLog alertLog) {
        alertLog.setUpdateTime(DateUtils.getNowDate());
        return alertLogMapper.updateAlertLogStatus(alertLog);
    }

    /**
     * 批量删除设备告警
     *
     * @param alertLogIds 需要删除的设备告警主键
     * @return 结果
     */
    @Override
    public int deleteAlertLogByAlertLogIds(Long[] alertLogIds) {
        return alertLogMapper.deleteAlertLogByAlertLogIds(alertLogIds);
    }

    /**
     * 删除设备告警信息
     *
     * @param alertLogId 设备告警主键
     * @return 结果
     */
    @Override
    public int deleteAlertLogByAlertLogId(Long alertLogId) {
        return alertLogMapper.deleteAlertLogByAlertLogId(alertLogId);
    }

    /**
     * 通过设备编号删除设备告警信息
     *
     * @param SerialNumber 设备告警主键
     * @return 结果
     */
    @Override
    public int deleteAlertLogBySerialNumber(String SerialNumber) {
        return alertLogMapper.deleteAlertLogBySerialNumber(SerialNumber);
    }

    @Override
    public List<AlertCountVO> countAlertProcess(DataCenterParam dataCenterParam) {
        return alertLogMapper.countAlertProcess(dataCenterParam);
    }

    @Override
    public List<AlertCountVO> countAlertLevel(DataCenterParam dataCenterParam) {
        return alertLogMapper.countAlertLevel(dataCenterParam);
    }

    @Override
    public AjaxResult listAlertLogEchartsByType(AlertLog alertLog) {

        AjaxResult ajaxResult = new AjaxResult();
        SysUser user = getLoginUser().getUser();
        // 查询所属机构
        if (null != user.getDeptId()) {
            alertLog.setUserId(user.getDept().getDeptUserId());
        } else {
            alertLog.setUserId(user.getUserId());
        }
        ;
        List<AlertLog> alertLogs = alertLogMapper.listAlertLogEchartsByType(alertLog);
        return ajaxResult.put("data", alertLogs);
    }

    @Override
    public AjaxResult listDeviceLogCount(AlertLog alertLog) {
        AjaxResult ajaxResult = new AjaxResult();
        SysUser user = getLoginUser().getUser();
        // 查询所属机构
        if (null != user.getDeptId()) {
            alertLog.setUserId(user.getDept().getDeptUserId());
        } else {
            alertLog.setUserId(user.getUserId());
        }
        ;
        List<AlertLog> alertLogs = alertLogMapper.listDeviceLogCount(alertLog);
        ajaxResult.put("data", alertLogs);
        return ajaxResult;
    }

    @Override
    public AjaxResult getIotProductCount() {
        List<AlertLog> iotProductCount = alertLogMapper.getIotProductCount();
        // 使用Stream API进行分组和计数
        Map<String, Long> topFiveProducts = iotProductCount.stream()
                .collect(Collectors.groupingBy(AlertLog::getProductName, Collectors.counting())) // 分组并计数
                .entrySet().stream() // 转换为Stream<Map.Entry<String, Long>>
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed()) // 根据值（计数）降序排序
                .limit(5) // 限制为前五个
                .collect(Collectors.toMap(
                        Map.Entry::getKey, // 键为productName
                        Map.Entry::getValue, // 值为计数
                        (existing, replacement) -> existing, // 合并函数，这里不会用到
                        () -> new LinkedHashMap<>())); // 使用LinkedHashMap以保持顺序
        AjaxResult ajaxResult = new AjaxResult();
        List<AlertLogVo> alertLogVoList = new ArrayList<>();
        for (Map.Entry<String, Long> entry : topFiveProducts.entrySet()) {
            // 在这里处理每个键值对
            AlertLogVo alertLogVo = new AlertLogVo();
            alertLogVo.setName(entry.getKey());
            alertLogVo.setValue(entry.getValue());
            alertLogVoList.add(alertLogVo);
        }
        ajaxResult.put("data", alertLogVoList);
        return AjaxResult.success(ajaxResult);
    }
}
